package tools;

import java.awt.Desktop;
import java.awt.print.PrinterJob;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;

import org.xhtmlrenderer.pdf.ITextRenderer;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.html.simpleparser.HTMLWorker;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;

public class GPrinterUtils {

	public static PrintService[] getPrinterList() {
		PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
		System.out.println("Number of print services: " + printServices.length);

		for (PrintService printer : printServices)
			System.out.println("Printer: " + printer.getName());
		return printServices;
	}

	public static PrintService getDefaultPrinter() {
		PrintService service = PrintServiceLookup.lookupDefaultPrintService();
		System.out.println(service.getName());
		return service;
	}

	public static void printPlainText(String plainText) {
		try {
			PrintService mPrinter = null;
			Boolean bFoundPrinter = false;

			PrintService[] printServices = PrinterJob.lookupPrintServices();

			//
			// Iterates the print services and print out its name.
			//
			for (PrintService printService : printServices) {
				String sPrinterName = printService.getName();
				if (sPrinterName.equals("HP Color ")) {
					mPrinter = printService;
					bFoundPrinter = true;
				}
			}
			System.out.println("Default Printer:" + mPrinter);
			System.out.println("Printer Found:" + bFoundPrinter);

			// Getting parameter plain text
			InputStream is = new ByteArrayInputStream(plainText.getBytes());
			DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;

			// Find the default service
			PrintService service = PrintServiceLookup.lookupDefaultPrintService();
			System.out.println(service);

			// Create the print job
			DocPrintJob job = service.createPrintJob();
			Doc doc = new SimpleDoc(is, flavor, null);

			// Monitor print job events; for the implementation of
			// PrintJobWatcher,
			PrintJobWatcher pjDone = new PrintJobWatcher(job);

			// Print it
			job.print(doc, null);

			// Wait for the print job to be done
			pjDone.waitForDone();

			// It is now safe to close the input stream
			is.close();
		} catch (PrintException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	static class PrintJobWatcher {
		// true iff it is safe to close the print job's input stream
		boolean done = false;

		PrintJobWatcher(DocPrintJob job) {
			// Add a listener to the print job
			job.addPrintJobListener(new PrintJobAdapter() {
				public void printJobCanceled(PrintJobEvent pje) {
					allDone();
				}

				public void printJobCompleted(PrintJobEvent pje) {
					allDone();
				}

				public void printJobFailed(PrintJobEvent pje) {
					allDone();
				}

				public void printJobNoMoreEvents(PrintJobEvent pje) {
					allDone();
				}

				void allDone() {
					synchronized (PrintJobWatcher.this) {
						done = true;
						PrintJobWatcher.this.notify();
					}
				}
			});
		}

		public synchronized void waitForDone() {
			try {
				while (!done) {
					wait();
				}
			} catch (InterruptedException e) {
			}
		}
	}

	/**
	 * Printing HTML file with given file path Example : "c:/test.html"
	 * 
	 * @param filePath
	 * @author galip.erdem
	 * */
	public static void printHTML(String filePath) {
		if (Desktop.isDesktopSupported()) {
			Desktop desktop = Desktop.getDesktop();
			if (desktop.isSupported(Desktop.Action.PRINT)) {
				try {
					URI uri = new URI(filePath);
					desktop.browse(uri);
					desktop.print(new File(filePath));
				} catch (IOException e) {
					System.out.println(desktop.isSupported(Desktop.Action.PRINT));
					System.out.println(new File(filePath));

					e.printStackTrace();
				} catch (URISyntaxException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	private static void converterHTMLtoPDF(String url, String outputFilePath) throws DocumentException, IOException {

		String outputFile = outputFilePath;
		OutputStream os = new FileOutputStream(outputFile);

		ITextRenderer renderer = new ITextRenderer();
		renderer.getFontResolver().addFont("C:\\Windows\\Fonts\\ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
		renderer.setDocument(url);
		renderer.layout();
		renderer.createPDF(os);

		os.close();
		System.out.println("Conversion from " + url + " to " + outputFile + " is successful!");
	}

	/* Needs to be tested */
	public static void convertHTMLtoPDF(URL inputFilePath, String outputFilePath) {
		String url;
		try {
			url = inputFilePath.toString();
			converterHTMLtoPDF(url, outputFilePath);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void convertHTMLtoPDF(URI inputFileURI, String outputFilePath) {
		String url;
		try {
			url = inputFileURI.toURL().toString();
			converterHTMLtoPDF(url, outputFilePath);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void convertHTMLtoPDFItext(String htmlText, String PdfSavePath) {
		Document document = new Document(PageSize.A4);
		PdfWriter pdfWriter = null;
		try {
			pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(PdfSavePath));

		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (DocumentException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		document.open();
		// document.addAuthor("Author of the Doc");
		// document.addCreator("Creator of the Doc");
		// document.addSubject("Subject of the Doc");
		document.addCreationDate();
		// document.addTitle("This is the title");
		// SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
		// SAXmyHtmlHandler shh = new SAXmyHtmlHandler(document);
		HTMLWorker htmlWorker = new HTMLWorker(document);
		try {
			htmlWorker.parse(new StringReader(htmlText));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		document.close();
		pdfWriter.close();
		System.out.println("PDF Created!");
	}

	/**
	 *
	 Using Flying Saucer libraries for HTML to PDF and PDF to HTML
	 * 
	 * @param inputFilePath
	 *            : Gets input file path. Example "c:/test.html"
	 * @param outputFilePath
	 *            : Saves output file path as pdf. Example "c:/test.pdf"
	 * @author galip.erdem
	 * */
	public static void convertHTMLtoPDFIText_Old(String htmlString, String outputFilePath) {
		Document document = new Document();
		try {
			PdfWriter.getInstance(document, new FileOutputStream(outputFilePath));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		document.open();
		Font font = new Font(Font.TIMES_ROMAN, 12, Font.BOLD);
		Paragraph pg = new Paragraph(htmlString);
		pg.setFont(font);
		// pg.add("Test ■ ...ä...ö... Test");
		try {
			Image image2 = Image.getInstance(new URL("http://sample.gevezecafe.com//images//logo-gevezecafe.png"));
			document.add(image2);
			document.add(pg);
		} catch (DocumentException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		document.close(); // and I get the two umlaut characters correct.

		String outputFile = outputFilePath;
		try {
			OutputStream os = new FileOutputStream(outputFile);
			os.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void browseLog(String logPath) {
		if (Desktop.isDesktopSupported()) {
			Desktop desktop = Desktop.getDesktop();
			if (desktop.isSupported(Desktop.Action.PRINT)) {
				URI logUri;
				try {
					logUri = new URI(logPath);
					desktop.browse(logUri);
				} catch (URISyntaxException e) {
					System.out.println("Problem while browsing log: Log file path error!");
					e.printStackTrace();
				} catch (IOException e) {
					System.out.println("Problem while browsing log: Log file error!");
					e.printStackTrace();
				}

			}
		}
	}
}
